package com.sugon.modules.device.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import com.sugon.dao.DevAmTicketItemDao;
import com.sugon.dao.DevFaultPreventMeasureDao;
import com.sugon.entity.DevAmTicketEntity;
import com.sugon.entity.DevAmTicketItemEntity;
import com.sugon.entity.DevMaintenancePlanChangeEntity;
import com.sugon.entity.TicketLiveImageEntity;
import com.sugon.modules.base.model.vo.ProcessProgressConst;
import com.sugon.modules.device.consts.DevFaultPreventProgress;
import com.sugon.modules.device.consts.DevMaintenanceItemExecuteStatus;
import com.sugon.modules.device.consts.DevMaintenanceTicketStatus;
import com.sugon.modules.device.model.vo.DelayCheckParam;
import com.sugon.modules.device.model.vo.DevMaintenanceDelayApplyParam;
import com.sugon.modules.device.service.IDeviceAmTicketManager;
import com.sugon.modules.utils.DateUtil;
import com.sugon.service.*;
import com.sugon.utils.MinioUtil;
import com.sugon.utils.ProcessInfoEnum;
import com.sugon.utils.R;
import com.sugon.utils.ShiroUtils;
import org.apache.shiro.util.Assert;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * @author ： YuXD
 * @description： 设备维护工单Manager实现类
 * @date ： 2020-11-18 下午 5:04
 * @version: 1.0
 */
@Service
public class DeviceAmTicketManagerImpl implements IDeviceAmTicketManager {

    @Resource
    private DevMaintenancePlanChangeService devMaintenancePlanChangeService;
    @Resource
    private DevAmTicketService devAmTicketService;
    @Resource
    private DevAmTicketItemService devAmTicketItemService;
    @Resource
    private SysMsgService sysMsgService;
    @Resource
    private DevReportUrgeService devReportUrgeService;
    @Resource
    private TicketLiveImageService ticketLiveImageService;
    @Resource
    private DevAmTicketItemDao devAmTicketItemDao;
    @Resource
    private SysOssService sysOssService;
    @Resource
    private DevFaultPreventMeasureDao devFaultPreventMeasureDao;

    /**
     * 催办
     *
     * @param ticketId 工单ID
     * @param userId   催办人ID
     * @return
     */
    @Override
    public synchronized boolean urge(String ticketId, String userId) {
        DevAmTicketEntity ticket = devAmTicketService.queryObject(ticketId);
        Assert.notNull(ticket, "维修工单不存在，工单ID: " + ticketId);
        // 1、更新维修工单状态
        ticket.setIsUrged(1);
        boolean flag = devAmTicketService.update(ticket) > 0;
        if (flag) {
            // 2、保存催办记录
            devReportUrgeService.save(ticketId, "MAINTENANCE");
            // 3、更新工单消息提醒
            sysMsgService.addRemindItem(ProcessInfoEnum.DEV_ZXGD, ticketId, ticket.getExecutor());
        }
        return flag;
    }

    /**
     * 申请变更
     *
     * @param ticketChangeApplyParam
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean applyChange(DevMaintenanceDelayApplyParam ticketChangeApplyParam) {
        DevAmTicketEntity ticket = ticketChangeApplyParam.getDevAmTicket();
        // 1、生成工单申请记录，并保存
        DevMaintenancePlanChangeEntity changeRecord = new DevMaintenancePlanChangeEntity();
        CopyOptions copyOptions = CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true);
        BeanUtil.copyProperties(ticketChangeApplyParam, changeRecord, copyOptions);
        changeRecord.setOriginalTime(ticket.getFinalEndTime());
        changeRecord.setApplier(ticketChangeApplyParam.getApplier());
        changeRecord.setProgress(ProcessProgressConst.DEPT_APPROVING);
        boolean flag = devMaintenancePlanChangeService.save(changeRecord) > 0;
        if (flag) {
            // 2、更改维修工单状态
            ticket.setStatus(DevMaintenanceTicketStatus.DELAY_APPLYING);
            devAmTicketService.update(ticket);
            // 3、生成审核信息和启动流程
            sysMsgService.addDevMaintenancePlanChangeApproveItem(ticket.getId(), 0);
        }
        return flag;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean completeDevMaintenanceOption(DevAmTicketItemEntity devAmTicketItem) {
        /*
            完成需要区分正常完成和延期完成两种情形
            逻辑：如果在规定时间内完成，那么属于正常完成，否则属于延期完成
         */
        Date executeDate = cn.hutool.core.date.DateUtil.date();
        DevAmTicketEntity maintenanceTicket = devAmTicketService.queryObject(devAmTicketItem.getDevMainTicketId());
        cn.hutool.core.lang.Assert.notNull(maintenanceTicket);
        Integer executeStatus;
        if (DateUtil.between(executeDate, maintenanceTicket.getStartTime(), maintenanceTicket.getFinalEndTime())) {
            executeStatus = DevMaintenanceItemExecuteStatus.ED;
        } else {
            executeStatus = DevMaintenanceItemExecuteStatus.DELAY_ED;
        }
        devAmTicketItem.setImplementDate(executeDate);
        devAmTicketItem.setStatus(executeStatus);
        // 更新设备维护工单项状态
        if (devAmTicketItemService.update(devAmTicketItem) > 0) {
            // 保存工单现场照片
            List<String> liveImageList = devAmTicketItem.getLiveImageList();
            if (CollectionUtil.isNotEmpty(liveImageList)) {
                ticketLiveImageService.batchUpdateTicketImages(devAmTicketItem.getId(), "AM", "维护现场", liveImageList);
            }
            // 调整工单状态
            adjustTicketStatus(devAmTicketItem.getDevMainTicketId());
        }
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean modifyLiveImage(DevAmTicketItemEntity amTicketItem, MultipartFile[] liveImageArray) {
        /*
            1、更新维护项信息
            2、删除已有的
            3、保存最新工单信息
         */
        amTicketItem.setImplementerId(ShiroUtils.getUserId());
        amTicketItem.setImplementDate(cn.hutool.core.date.DateUtil.date());
        // 更新设备维护工单项状态
        if (devAmTicketItemService.update(amTicketItem) > 0) {
            // 删除已有的工单执行现场照片
            List<TicketLiveImageEntity> existsLiveImages = ticketLiveImageService.queryList(amTicketItem.getId(), "AM");
            if (CollectionUtil.isNotEmpty(existsLiveImages)) {
                for (TicketLiveImageEntity existsLiveImage : existsLiveImages) {
                    // 删除原工单现场照片
                    MinioUtil.removeObject("erms", existsLiveImage.getPath());
                    // 删除原工单现场照片记录
                    ticketLiveImageService.delete(existsLiveImage.getId());
                }
            }
            // 保存最新工单现场照片
            for (MultipartFile liveImage : liveImageArray) {
                R uploadResult = sysOssService.upload("device", "am", liveImage);
                if (uploadResult != null && uploadResult.containsKey("url")) {
                    ticketLiveImageService.addTicketLiveImage(amTicketItem.getId(), "AM", (String) uploadResult.get("url"));
                }
            }
        }
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean checkChange(DelayCheckParam delayCheckParam) {
        DevMaintenancePlanChangeEntity applyRecord = delayCheckParam.getApplyRecord();
        cn.hutool.core.lang.Assert.notNull(applyRecord);
        applyRecord.setChecker(ShiroUtils.getUserId());
        applyRecord.setProgress(delayCheckParam.getApprovalStatus());
        boolean flag = devMaintenancePlanChangeService.update(applyRecord) > 0;
        if (flag) {
            DevAmTicketEntity ticket = delayCheckParam.getAmTicket();
            cn.hutool.core.lang.Assert.notNull(applyRecord);
            ticket.setStatus(DevMaintenanceTicketStatus.DELAY_MAINTAINING);
            ticket.setFinalEndTime(applyRecord.getChangeTime());
            devAmTicketService.update(ticket);
        }
        return flag;
    }

    /**
     * 调整工单状态
     *
     * @param devMaintenanceTicketId 设备维护工单ID
     * @return
     */
    private void adjustTicketStatus(String devMaintenanceTicketId) {
        /*
            获取当前维护工单的状态
            如果是非维护中的状态：那么需要更新工单状态、接收时间和执行时间字段
            如果是维护中状态：校验是否所有的工单项都结束？如果是那么更新工单状态为已完成
         */
        DevAmTicketEntity devAmTicket = devAmTicketService.queryObject(devMaintenanceTicketId);
        if (DevMaintenanceTicketStatus.WAIT_EXECUTE.equals(devAmTicket.getStatus())) {
            // 校验工单是否刚刚开始，如果是，则修改接单时间和开始时间
            int completedNum = devAmTicketItemDao.countTicketOptionNum(devMaintenanceTicketId, DevMaintenanceItemExecuteStatus.DELAY_ED, DevMaintenanceItemExecuteStatus.ED);
            if (completedNum > 0) {
                devAmTicket.setStatus(DevMaintenanceTicketStatus.MAINTAINING);
                devAmTicketService.update(devAmTicket);
                // 调整预防措施进度
                devFaultPreventMeasureDao.updateProgress(devMaintenanceTicketId, DevFaultPreventProgress.ING, "DEV_MAINTENANCE_TICKET_AM");
            }
        }
        // 校验工单的所有维护项是否已完成，如果已完成，那么修改工单状态为已完成
        int uncompletedNum = devAmTicketItemDao.countTicketOptionNum(devMaintenanceTicketId, DevMaintenanceItemExecuteStatus.UN);
        if (uncompletedNum == 0) {
            Integer status;
            if (DateUtil.between(cn.hutool.core.date.DateUtil.date(), devAmTicket.getStartTime(), devAmTicket.getFinalEndTime())) {
                status = DevMaintenanceTicketStatus.COMPLETE;
            } else {
                status = DevMaintenanceTicketStatus.DELAY_COMPLETE;
            }
            devAmTicket.setStatus(status);
            devAmTicketService.update(devAmTicket);
            // 调整预防措施进度
            devFaultPreventMeasureDao.updateProgress(devMaintenanceTicketId, DevFaultPreventProgress.ED, "DEV_MAINTENANCE_TICKET_AM");
        }
    }
}
